package com.bdqn.qnnews.common.redis.utils;

import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.types.Expiration;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 * @author xlzhang
 * @date 2024/1/12 9:14
 */
public class RedisUtils {
    private final StringRedisTemplate stringRedisTemplate;
    public RedisUtils(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 加锁：利用redis的单线程特性和setnx特性实现
     * @param key key
     * @param expireSeconds 过期时间 单位秒
     * @return 随机值
     */
    public String tryLock(String key, long expireSeconds){
        key = key + "_lock";
        // 生成一个唯一的值作业锁的value
        final String token = UUID.randomUUID().toString();

        final RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory();
        assert factory != null;
        final RedisConnection conn = factory.getConnection();
        try {
            // set key value[expiration EX seconds|PX milliseconds] [NX|XX]
            final Boolean result = conn.set(
                    key.getBytes(),
                    token.getBytes(),
                    Expiration.from(expireSeconds, TimeUnit.SECONDS),
                    RedisStringCommands.SetOption.SET_IF_ABSENT
            );
            if (result!=null && result){
                return token;
            }
        } finally {
            RedisConnectionUtils.releaseConnection(conn,factory);
        }
        return null;
    }
}